/*	See licence.txt for licence. Expd S-Expressions for D*/
module expd.treebuild;
import expd.itoken;
import expd.base;
import expd.tree;
import expd.itree;
import expd.node;

version(dbg)
{
    import expd.meta;
    mixin (DebugTrick());
}
class TreeBuilder : Streamable!(Token[])
{
    ulong parens = 0;
    alias node!Token Node;
    ITree!Token ourTree;
    Streamable!(ITree!Token) outchannel;
    this()
    {
        ourTree = new ETree!Token();
    }
    void push(Token[] a)
    {
        version(dbg3) synchronized _objout("TREE: flushed into Treebuilder");
        if(outchannel is null) throw new TreeBuildingEException("output is null");
        foreach(tok; a)
        {
            version(dbg3) synchronized _objout("TREE: building token (",tok,")");
            switch(tok.type)
            {
            case TOKEN.O_PAR:
                parens++;
                ourTree.add(Node(tok));
                ourTree.selectLast();
                break;
            case TOKEN.C_PAR:
                parens--;
                ourTree.up();
                break;
            default:
                ourTree.add(Node(tok));
                break;

            }
        }
        version(dbg3) synchronized
        {
            _objout("TREE: now tree ",ourTree);
        }

    }
    void flush()
    {
        version(dbg3) synchronized
        {
            _objout("TREE: flushing ",ourTree);
        }
        if(parens == 0)outchannel.push(ourTree);
        else throw new TreeBuildingEException("mismatched parents");
    }
    void setChannel(Streamable!(ITree!Token) x)
    {
        outchannel = x;
    }
    Streamable!(ITree!Token) getChannel()
    {
        return outchannel;
    }
}
